home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / boot / czesc_1 / beep / play.c < prev    next >
C/C++ Source or Header  |  1992-01-18  |  5KB  |  257 lines

  1. /*
  2.  * play.c - routines to load and play an IFF 8SVX sound
  3.  *
  4.  * Bruno Costa - 19 Feb 91 - 19 Feb 91
  5.  *
  6.  * (based on ARKM 1.3 example audio2.c)
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <devices/audio.h>
  12. #include <libraries/dos.h>
  13. #include <graphics/gfxbase.h>
  14. #include <proto/exec.h>
  15. #include <proto/dos.h>
  16.  
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19.  
  20. #include "iff.h"
  21.  
  22. #define VHDR MakeID('V','H','D','R')
  23. #define BODY MakeID('B','O','D','Y')
  24. #define MY8S MakeID('8','S','V','X')
  25.  
  26.  
  27. static struct MsgPort *port;        /* audio device port */
  28.  
  29. static UBYTE *fbuf;            /* For sample memory allocation */
  30. static ULONG fsize;            /* and freeing                  */
  31.  
  32. static Voice8Header *header;
  33. static UBYTE *sample;            /* one-shot sample data        */
  34. static ULONG length;            /* Sample length               */
  35. static ULONG clock;
  36.  
  37. static struct IOAudio *AIOreq;
  38. static int posted = FALSE;
  39.  
  40.  
  41. static void setclock (void)
  42. {
  43.  struct GfxBase *gbase;
  44.  
  45.  clock = 3579545L;        /* NTSC clock */
  46.  
  47.  gbase = (struct GfxBase *) OpenLibrary ("graphics.library", 0L);
  48.  if (gbase)
  49.  {
  50.    if (gbase->DisplayFlags & PAL)
  51.      clock = 3546895L;        /* PAL clock */
  52.  
  53.    CloseLibrary ((struct Library *) gbase);
  54.  }
  55. }
  56.  
  57.  
  58. static void abort (void)
  59. {
  60.  if (posted && !CheckIO ((struct IORequest *) AIOreq))
  61.    AbortIO ((struct IORequest *) AIOreq);
  62. }
  63.  
  64.  
  65. static void wait (void)
  66. {
  67.  if (posted)
  68.  {
  69.    WaitPort (port);
  70.    (void) GetMsg (port);
  71.    posted = FALSE;
  72.  }
  73. }
  74.  
  75.  
  76. static int sopen (void)
  77. {
  78.  static UBYTE chan1[]  = { 1 };        /* Audio channel allocation arrays */
  79.  static UBYTE chan2[]  = { 2 };
  80.  static UBYTE chan3[]  = { 4 };
  81.  static UBYTE chan4[]  = { 8 };
  82.  static UBYTE *chans[] = {chan1,chan2,chan3,chan4};
  83.  
  84.  ULONG speed = clock / header->samplesPerSec;
  85.  
  86.  AIOreq = (struct IOAudio *) AllocMem (sizeof (*AIOreq), MEMF_PUBLIC | MEMF_CLEAR);
  87.  if (AIOreq)
  88.  {
  89.    port = CreatePort (0, 0);
  90.    if (port)
  91.    {
  92.      int err;
  93.      int c = 0;        /* start by channel 0 */
  94.  
  95.      do
  96.      {
  97.        AIOreq->ioa_Request.io_Message.mn_ReplyPort   = port;
  98.        AIOreq->ioa_Request.io_Message.mn_Node.ln_Pri = 128;  /* No stealing! */
  99.        AIOreq->ioa_AllocKey                          = 0;
  100.        AIOreq->ioa_Data                              = chans[c];
  101.        AIOreq->ioa_Length                            = 1;
  102.  
  103.        err = OpenDevice ("audio.device", 0L, (struct IORequest *) AIOreq, 0L);
  104.        ++c;
  105.      } while (err != 0  &&  c < 4);
  106.  
  107.      if (!err)
  108.      {
  109.        AIOreq->ioa_Request.io_Command = CMD_WRITE;
  110.        AIOreq->ioa_Request.io_Flags = ADIOF_PERVOL;
  111.        AIOreq->ioa_Volume = 60;
  112.  
  113.        AIOreq->ioa_Period = (UWORD)speed;
  114.        AIOreq->ioa_Cycles = 1;
  115.  
  116.        AIOreq->ioa_Request.io_Message.mn_ReplyPort = port;
  117.  
  118.        AIOreq->ioa_Data = sample;
  119.  
  120.        return TRUE;        /* normal return is here */
  121.      }
  122.      DeletePort (port);
  123.    }
  124.    FreeMem (AIOreq, sizeof (*AIOreq));
  125.  }
  126.  
  127.  return FALSE;
  128. }
  129.  
  130.  
  131. static void sclose (void)
  132. {
  133.  abort ();
  134.  wait ();
  135.  
  136.  CloseDevice ((struct IORequest *) AIOreq);
  137.  if (port)
  138.    DeletePort (port);
  139.  if (AIOreq)
  140.    FreeMem (AIOreq, sizeof (*AIOreq));
  141. }
  142.  
  143.  
  144. void play (void)
  145. {
  146.  abort ();
  147.  wait ();
  148.  
  149.  if (length > 0  &&  length <= 102400)
  150.  {
  151.    AIOreq->ioa_Length = length;
  152.    BeginIO ((struct IORequest *) AIOreq);
  153.    posted = TRUE;
  154.  }
  155. }
  156.  
  157.  
  158. int load (char *fname)
  159. {
  160.  UBYTE *data;        /* data ptr for file read    */
  161.  BYTE iobuffer[8];    /* Buffer for 8SVX header    */
  162.  Chunk *chunk;        /* Pointers for 8SVX parsing */
  163.  BPTR f;
  164.  
  165.  setclock ();
  166.  
  167.  f = Open (fname, MODE_OLDFILE);
  168.  if (f)
  169.  {
  170.    long count = Read (f, iobuffer, 8L);
  171.    if (count == 8)
  172.    {
  173.      chunk = (Chunk *)iobuffer;
  174.      if(chunk->ckID == FORM)
  175.      {
  176.        fsize = chunk->ckSize;
  177.        fbuf = AllocMem (fsize, MEMF_CHIP | MEMF_CLEAR);
  178.        if (fbuf)
  179.        {
  180.          data = fbuf;
  181.          count = Read (f, fbuf, chunk->ckSize);
  182.          if (count == chunk->ckSize)
  183.          {
  184.            if (MakeID (*data, *(data+1), *(data+2), *(data+3)) == MY8S)
  185.            {
  186.              data += 4;
  187.  
  188.              while (data < fbuf + fsize)
  189.              {
  190.                chunk = (Chunk *)data;
  191.  
  192.                switch (chunk->ckID)
  193.                {
  194.                  case VHDR:
  195.                    header = (Voice8Header *) (data + 8);
  196.                    break;
  197.  
  198.                  case BODY:
  199.                    sample = (BYTE *)(data + 8);
  200.                    length = header->oneShotHiSamples;
  201.                    if (length == 0)
  202.                      length = header->repeatHiSamples;
  203.                    break;
  204.                }
  205.  
  206.                data += 8 + chunk->ckSize;
  207.  
  208.                if (chunk->ckSize & 1L == 1)
  209.                  data++;
  210.              }
  211.              Close (f);
  212.  
  213.              if (sopen ())
  214.                return TRUE;    /* normal exit is here */
  215.            }
  216.          }
  217.          FreeMem (fbuf, fsize);
  218.        }
  219.      }
  220.    }
  221.    Close (f);
  222.  }
  223.  
  224.  return FALSE;
  225. }
  226.  
  227.  
  228. void unload (void)
  229. {
  230.  sclose ();
  231.  
  232.  if (fbuf)
  233.    FreeMem (fbuf, fsize);
  234.  
  235.  fbuf = NULL;
  236.  fsize = 0;
  237. }
  238.  
  239.  
  240. #ifdef TEST
  241. void main (int argc, char *argv[])
  242. {
  243.  if (argc != 2)
  244.  {
  245.    printf ("usage: %s <sound file>\n", argv[0]);
  246.    exit (10);
  247.  }
  248.  
  249.  if (load (argv[1]))
  250.  {
  251.    play ();
  252.    wait ();
  253.    unload ();
  254.  }
  255. }
  256. #endif
  257.